var {appUtils, timeUtils, randomUtils, logUtils} = require ('../utils/index');

/**
 * @typedef Config {
 *        maxAllowRunHour?:Number
 *        minAllowRunHour?:Number
 *        maxRunSCount?:Number?
 *        maxRunFCount?:Number?
 *        maxRunTCount?:Number?
 * }
 * @param {string} name
 * @param {Config} config
 */
function App (name, config) {
  this.name = name;
  this.storage = storages.create (timeUtils.str () + this.name);
  this.maxAllowRunHour = config.maxAllowRunHour;
  this.minAllowRunHour = config.minAllowRunHour;
  this.maxRunSCount = config.maxRunSCount;
  this.maxRunFCount = config.maxRunFCount;
  this.maxRunTCount = config.maxRunTCount;
  this.maxOpenCount = config.maxOpenCount;
  this.interval = config.interval;
  this.installed = null;
  this.todayIsOver = false;
  Object.defineProperty (this, 'runSCount', {
    get () {
      return this.storage.get (this.name + 'runSCount') || 0;
    },
    set (value) {
      this.storage.put (this.name + 'runSCount', value);
    },
  });
  Object.defineProperty (this, 'runFCount', {
    get () {
      return this.storage.get (this.name + 'runFCount') || 0;
    },
    set (value) {
      this.storage.put (this.name + 'runFCount', value);
    },
  });
  Object.defineProperty (this, 'openCount', {
    get () {
      return this.storage.get (this.name + 'openCount') || 0;
    },
    set (value) {
      this.storage.put (this.name + 'openCount', value);
    },
  });
  if (this.maxRunTCount) {
    Object.defineProperty (this, 'runTCount', {
      get () {
        return this.storage.get (this.name + 'runTCount') || 0;
      },
      set (value) {
        this.storage.put (this.name + 'runTCount', value);
      },
    });
  }
}
App.prototype.reset = function () {};
App.prototype.main = function () {
  if (this.checkInstalled ()) {
    if (this.maxRunTCount && this.maxRunTCount > this.runTCount) {
      logUtils.log (
        this.name + '开始测试运行',
        this.runTCount,
        '/',
        this.maxRunTCount
      );
      this.open ();
      sleep (randomUtils.getRandom (6, 8, 1000));
      this.runTest (this.runTCount);
      this.runTCount++;
      this.close ();
      logUtils.log (this.name + '结束测试运行');
      return;
    }
  }
  if (this.canRun ()) {
    logUtils.log (this.name + '开始运行', this.openCount);
    this.open ();
    this.openCount++;
    this.lastStartTime = Date.now ();
    sleep (randomUtils.getRandom (6, 8, 1000));
    this.run ();
    this.close ();
    this.lastEndTime = Date.now ();
    logUtils.log (this.name + '结束运行');
  }
};
App.prototype.open = function () {
  return appUtils.open (this.name);
};
App.prototype.close = function () {
  return appUtils.closeRecent (this.name);
};
App.prototype.canRun = function () {
  if (!this.checkOpenCount ()) {
    return;
  }
  if (!this.checkInstalled ()) {
    return;
  }
  if (!this.checkAllowRunHour ()) {
    return;
  }
  if (!this.checkRunCount ()) {
    return;
  }
  if (!this.checkInterval ()) {
    return;
  }

  if (this.todayIsOver) {
    return;
  }
  return true;
};
App.prototype.run = function () {
  throw new Error ('App.run must be implemented');
};
App.prototype.runTest = function () {
  throw new Error ('App.runTest must be implemented');
};
App.prototype.checkOpenCount = function () {
  if (this.maxOpenCount) {
    logUtils.info (this.openCount + '/' + this.maxOpenCount);
    if (this.openCount >= this.maxOpenCount) {
      logUtils.info (
        this.name,
        '打开次数超过限制',
        this.openCount,
        '|',
        this.maxOpenCount
      );
      return false;
    }
  } else {
    logUtils.info ('this.maxOpenCount 未定义');
  }
  return true;
};
App.prototype.checkInstalled = function () {
  if (this.installed === null) {
    this.installed = appUtils.checkInstalled (this.name);
    if (!this.installed) {
      logUtils.info ('checkInstalled: ' + this.name + ' 未安装');
    }
  }
  return this.installed;
};
App.prototype.checkInterval = function () {
  if (this.interval && this.lastEndTime) {
    var hasExec = timeUtils.hasExec (this.lastEndTime);
    var interval = this.interval;
    if (hasExec < interval) {
      logUtils.info (this.name, '间隔时间未到', hasExec, '/', this.interval);
      return false;
    }
  }
  return true;
};
App.prototype.checkAllowRunHour = function () {
  var hour = new Date ().getHours ();
  if (this.maxAllowRunHour) {
    if (hour >= this.maxAllowRunHour) {
      logUtils.info (this.name, hour, '|', maxAllowRunHour, '最大允许执行时间已过');
      return false;
    }
  }
  if (this.minAllowRunHour) {
    if (hour < this.minAllowRunHour) {
      logUtils.info (this.name, hour, '|', minAllowRunHour, '最小允许执行时间未到');
      return false;
    }
  }
  return true;
};
App.prototype.checkRunCount = function () {
  if (this.maxRunSCount) {
    if (this.runSCount >= this.maxRunSCount) {
      logUtils.info (
        this.name,
        this.runSCount,
        '|',
        this.maxRunSCount,
        '执行成功次数超过限制'
      );
      return false;
    }
  }
  if (this.maxRunFCount) {
    if (this.runFCount >= this.maxRunFCount) {
      logUtils.info (
        this.name,
        this.runFCount,
        '|',
        this.maxRunFCount,
        '执行失败次数超过限制'
      );
      return false;
    }
  }
  return true;
};
module.exports = App;
